/***************************************************************
 * Name:      cameraMain.cpp
 * Purpose:   Code for Application Frame
 * Author:     ()
 * Created:   2024-01-02
 * Copyright:  ()
 * License:
 **************************************************************/

#ifdef WX_PRECOMP
#include "wx_pch.h"
#endif

#ifdef __BORLANDC__
#pragma hdrstop
#endif //__BORLANDC__

#include "cameraDialog.h"
#include <wx/dcclient.h>
#include <wx/dcscreen.h>
#include <wx/dcmemory.h>

#define IP "localhost"
#define PORT 10001

#include <filesystem>
wxDEFINE_EVENT(SOCKET_ID, wxSocketEvent);
BEGIN_EVENT_TABLE(cameraDialog, wxDialog)
    EVT_SOCKET(SOCKET_ID,    cameraDialog::OnSocketEvent)
END_EVENT_TABLE()
cameraDialog::cameraDialog(wxDialog *dlg)
    : CameraGUI(dlg)
{
    TcpConnect();
}

cameraDialog::~cameraDialog()
{
    mExit=true;
}
void cameraDialog::TcpConnect()
{
    wxIPV4address addr;
    addr.Hostname(wxT(IP));
    addr.Service(PORT);
    mTcp.SetEventHandler(*this, SOCKET_ID);
    mTcp.SetNotify(wxSOCKET_CONNECTION_FLAG|wxSOCKET_INPUT_FLAG|wxSOCKET_LOST_FLAG);
    mTcp.Notify(true);
    mTcp.Connect(addr,false);
}
void cameraDialog::UdpConnect()
{
    wxIPV4address addr;
    addr.Hostname(wxT(IP));
    addr.Service(PORT+1);
    mUdp.SetEventHandler(*this, SOCKET_ID);
    mUdp.SetNotify(wxSOCKET_CONNECTION_FLAG|wxSOCKET_INPUT_FLAG|wxSOCKET_LOST_FLAG);
    mUdp.Notify(true);
    mUdp.Connect(addr,false);
}
void cameraDialog::OnClose(wxCloseEvent &event)
{
    Destroy();
}
void cameraDialog::OnInitDialog( wxInitDialogEvent& event )
{
    std::thread([&]{
        while(!mExit){
            wxMemoryDC memDC;
            wxScreenDC dcScreen;

            wxCoord screenWidth, screenHeight;
            dcScreen.GetSize(&screenWidth, &screenHeight);
            wxRect rt= m_staticCamera->GetClientRect();

            wxBitmap fullscreen;
            fullscreen.Create(screenWidth,screenHeight);
            memDC.SelectObject(fullscreen);
            memDC.StretchBlit(0,0,rt.width,rt.height,&dcScreen, 0, 0, GetDeviceCaps(memDC.AcquireHDC(), DESKTOPHORZRES),GetDeviceCaps(memDC.AcquireHDC(), DESKTOPVERTRES));
            memDC.SelectObject(wxNullBitmap);
            mBitmaps.emplace_back(fullscreen);

            std::this_thread::sleep_for(std::chrono::milliseconds(100));
        }
    }).detach();

    std::thread([&]{
        while(!mExit){
            if(mBitmaps.size()>0){
                wxClientDC dc(m_staticCamera);
                wxBitmap image = mBitmaps.front();
                mBitmaps.pop_front();
                dc.DrawBitmap(image,wxPoint(0,0));

                RECT rtt;
                wxRect rt= m_staticCamera->GetClientRect();
                rtt.right=rt.GetWidth();
                rtt.bottom=rt.GetHeight();
                InvalidateRect(GetHWND(), &rtt, false);
            }
            std::this_thread::sleep_for(std::chrono::milliseconds(100));
        }
    }).detach();
}
void cameraDialog::OnSocketEvent(wxSocketEvent& event)
{
    wxIPV4address local_addr;
    wxSocketBase *sock = event.GetSocket();
    switch(event.GetSocketEvent())
    {
        case wxSOCKET_INPUT:{
            if(sock->GetLocal(local_addr)){
                if(local_addr.Service()==PORT){
                    char buf;
                    sock->Read(&buf, 1);
                    UdpConnect();
                }
            }
            break;
        }
        case wxSOCKET_LOST:{
            TcpConnect();
            break;
        }
        case wxSOCKET_CONNECTION:{
            break;
        }
        default:break;
    }
}
